package com.simon.cdc.yml;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.setting.yaml.YamlUtil;
import com.simon.cdc.config.AppConfig;
import com.simon.cdc.utils.ParameterParseUtil;

import java.io.File;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.Reader;

public class YamlConfigLoader {

    private static AppConfig appConfig;
    /**
     * 加载默认配置方法
     * 该方法尝试从类路径中的"application.yml"文件加载应用程序的默认配置
     * 使用try-with-resources语句来确保在操作流之后能够自动关闭资源，防止资源泄露
     * 当配置文件成功加载后，会将配置内容映射到AppConfig对象中
     * 如果配置文件加载失败或出现任何异常，该方法将抛出运行时异常，便于调用者处理错误情况
     */
    public static void loadDefaultConfig() {
        // 使用try-with-resources语句确保资源在使用后能被正确关闭
        try (Reader reader = new InputStreamReader(ResourceUtil.getStream("application.yml"))) {
            // 通过YamlUtil工具类将配置文件内容加载到AppConfig对象中
            appConfig = YamlUtil.load(reader, AppConfig.class);
        } catch (Exception e) {
            // 如果加载配置文件时发生异常，则抛出运行时异常
            throw new RuntimeException("加载默认配置失败", e);
        }
    }

    /**
     * 加载指定路径的配置文件
     * 此方法用于在运行时动态加载外部配置文件，以便应用程序可以根据外部配置调整其行为
     *
     * @param configPath 配置文件的路径字符串，不应为null或空，否则将抛出异常
     * @throws RuntimeException 如果指定路径的配置文件不存在或读取配置文件时发生错误，将抛出此异常
     */
    public static void loadExternalConfig(String configPath) {
        // 根据配置文件路径创建File对象
        File file = FileUtil.file(configPath);
        // 检查配置文件是否存在，如果不存在则抛出异常
        if (!file.exists()) {
            throw new RuntimeException("配置文件不存在: " + configPath);
        }
        // 使用try-with-resources确保文件读取后正确关闭资源
        try (Reader reader = new FileReader(file)) {
            // 通过YamlUtil工具类加载配置文件内容到AppConfig对象
            appConfig = YamlUtil.load(reader, AppConfig.class);
        } catch (Exception e) {
            // 如果在加载配置过程中发生任何错误，抛出包含原始异常的RuntimeException
            throw new RuntimeException("加载外部配置失败: " + configPath, e);
        }
    }


    /**
     * 获取当前应用的配置实例
     * 如果配置实例尚未初始化，则调用loadDefaultConfig方法进行初始化
     * 此方法确保了配置的单例模式，即在整个应用中配置实例是唯一的
     *
     * @return AppConfig实例，用于管理应用的配置信息
     */
    public static AppConfig getConfig() {
        // 检查配置实例是否已经存在，如果不存在则加载默认配置
        if (appConfig == null) {
            loadDefaultConfig(); // 默认加载
        }
        return appConfig;
    }

    /**
     * 初始化配置，支持解析 --jobConfig=<path> 格式参数
     *
     * @param args 命令行参数数组（支持 null 或空数组）
     */
    public static void init(String... args) {
        // 解析配置文件路径，如果没有指定则默认使用 "application.yml"
        String configPath = ParameterParseUtil.parseArgs(args,"--jobConfig=").orElse("application.yml");
        // 加载配置文件
        loadConfig(configPath);
    }



    /**
     * 加载配置文件
     * 该方法首先检查提供的配置文件路径是否有效如果路径有效，则加载外部配置；
     * 否则，加载默认配置
     *
     * @param configPath 配置文件的路径如果为null或空字符串，则忽略此参数
     */
    private static void loadConfig(String configPath) {
        // 检查配置文件路径是否有效
        if (configPath != null && !configPath.trim().isEmpty()) {
            // 路径有效时，加载外部配置
            loadExternalConfig(configPath);
        } else {
            // 路径无效时，加载默认配置
            loadDefaultConfig();
        }
    }

}